#!/usr/bin/perl -w

###############################################################################
# Transform the pheno input files into a two database load files, one for the
# pheno table and one for the pheno_details table
#
# Parameters needed: dbname, username, pheno_files, idlink_files, temp_dir
# Output files: temp_dir/pheno.out, temp_dir/phenodetails.out
#
# Author: Herodotos Herodotou and Nedyalko Borisov
# Date: March 11, 2010
#
##############################################################################

use getOpts qw(get_options println);
sub get_existing_patients;
sub create_exp_to_patient_map;

if ($#ARGV != 0)
{
   println qq(Please specify the .properties file);
   println qq(Usage: perl $0 load.properties);
   exit(-1);
}

# Get input parameters
%opt = get_options($ARGV[0]);
$DB_NAME  =$opt{'dbname'};
$USERNAME =$opt{'username'};
$PHENO_FILES = $opt{'pheno_files'};
$ID_LINK_FILES = $opt{'idlink_files'};
$TEMP_DIR = $opt{'temp_dir'};

# Open output files
open OUTFILE1, ">", $TEMP_DIR."/pheno.out" or die $!;
open OUTFILE2, ">", $TEMP_DIR."/pheno_details.out" or die $!;

# Get the existing patient ids from the database
%patients = get_existing_patients();

# Create a mapping exp_id -> patient_id
%exp_to_patient = create_exp_to_patient_map();

# Perform the transformation
@phenofiles = split(/;/, $PHENO_FILES);

foreach (@phenofiles)
{
    $phenofile = $_;
    $phenofile =~ s/\s+$//;
    $num_records = 0;
    
    # Open input pheno file
    println qq(Transform pheno file: $phenofile);
    open INFILE, "<", $phenofile or die $!;

    # Process the header line
    $line = <INFILE>;
    $line =~ s/\s+$//;
    @headers = split(',', $line);
    $num_cols=@headers;

    while($line = <INFILE>)
    {
       # Get the data
       $line =~ s/\s+$//;
       @data = split(/,/, $line);
       
       # Print pheno and details if patient is not already in the database
       $patient = $exp_to_patient{$data[1]};
       if (!exists $patients{$patient})
       {
          $sex = ($data[4] == 1) ? 'M' : 'F';
          
          if ($num_cols < 7)
          {
              print OUTFILE1 qq($patient,$sex,NULL\n);
          }
          else
          {
              print OUTFILE1 qq($patient,$sex,$data[6]\n);
          }
          
          for ($i = 7; $i < $num_cols; $i++)
          {
             # In affy, the sampleid is in the pheno files - do not add in pheno_details
             if ($headers[$i] !~ m/sampleid/i)
             {
                print OUTFILE2 qq($patient,$headers[$i],$data[$i]\n);
             }
          }
          
          # Insert in the map to avoid duplicate insertion
          $patients{$patient} = '';
          ++$num_records;
       }
    }


    # Close file
    close INFILE;
    println qq(Done pheno file transformation - produced $num_records records);
}

# Done
close OUTFILE1;
close OUTFILE2;


###############################################################################
# Function: get_existing_patients
#
# Input: none
#
# Description: This function returns a map containing all existing patient
#              ids in the database.
#
##############################################################################
sub get_existing_patients()
{
    # Create and execute the query
    my $query = qq(SELECT patient_id FROM pheno);
    !system qq(psql -U $USERNAME -d $DB_NAME -c "$query" -t -o $TEMP_DIR/patient_ref) or die $!;

    # Load the reference file in the patients map
    open INFILE, "<", "$TEMP_DIR/patient_ref" or die $!;

    my %patients = ();
    while ($line = <INFILE>)
    {
       $line =~ s/\s+$//;
       $line =~ s/^\s+//;
       $patients{$line} = '';
    }

    close INFILE;
    !system qq(rm -f $TEMP_DIR/patient_ref) or die $!;
    
    return %patients;
}


###############################################################################
# Function: create_ref_exp_to_patient
#
# Input: none
#
# Description: This function creates a returns a mapping key->value,
#              where the key is the exp_id and the value is the patient_id.
#
##############################################################################
sub create_exp_to_patient_map()
{
    my @idlinkfiles = split(/;/, $ID_LINK_FILES);
    my %exp_to_patient = ();

    foreach (@idlinkfiles)
    {
        # Open file
        $idlinkfile = $_;
        $idlinkfile =~ s/\s+$//;
        open INFILE, "<", $idlinkfile or die $!;

        $line = <INFILE>; # Ignore the header line
        while($line = <INFILE>)
        {
            # Read the mapping
           $line =~ s/\s+$//;
           @data = split(/,/, $line);
           $exp_to_patient{$data[1]} = $data[2];
        }

        # Close file
        close INFILE;
    }

   return %exp_to_patient;
}

